home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / pmode / pmode251 / pmode.asm < prev    next >
Assembly Source File  |  1994-11-29  |  69KB  |  2,040 lines

  1. ; PMODE v2.51 raw, DPMI, VCPI, & XMS compliant protected mode header.
  2. ; By Tran (a.k.a. Thomas Pytel).
  3.  
  4.         .386p
  5.  
  6. LOWMIN          = 0             ; minimum free low memory (in K)
  7. EXTMIN          = 0             ; minimum free extended memory (in K)
  8. SELECTORS       = 8             ; extra selectors for allocation
  9. STAKMAIN        = 100h          ; main execution stream stack size (in para)
  10. STAKRMODE       = 10h           ; real mode call stack size (in para)
  11. STAKPMODE       = 20h           ; protected mode call stack size (in para)
  12. MODENESTING     = 8             ; max number of nested mode switches
  13.  
  14. RMODENUM        = (MODENESTING+1) shr 1
  15. PMODENUM        = MODENESTING shr 1
  16. STAKSIZE        = STAKMAIN+(PMODENUM*STAKPMODE)+(RMODENUM*STAKRMODE)
  17.  
  18. DETECTORDER     = 1             ; 0 = DPMI then VPCI, 1 = VCPI then DPMI
  19.  
  20. .errnz STAKSIZE gt 0fffh        ; error if stack greater than 64k
  21.  
  22. code16  segment para public use16
  23. code16  ends
  24. code32  segment para public use32
  25. code32  ends
  26. codeend segment para stack use32 'stack'
  27. codeend ends
  28.  
  29. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  30. ; Real mode and 16bit code
  31. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  32. code16  segment para public use16
  33.         assume cs:code16, ds:code16
  34.         org 0
  35.  
  36. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  37. ; 16 bit common system data
  38. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  39. errmsg0         db      '386 or better not detected!!!',7,'$'
  40. errmsg1         db      'Not enough low memory!!!',7,'$'
  41. errmsg2         db      'System is already in V86 mode, and no VCPI or DPMI found!!!',7,'$'
  42. errmsg3         db      'Not enough extended memory!!!',7,'$'
  43. errmsg4         db      'Couldn''t enable A20 gate!!!',7,'$'
  44. errmsg5         db      'Extended memory allocation failure. (weird eh???)',7,'$'
  45.  
  46. nullint         db      0cfh            ; IRET instruction
  47. exitrout        dw      exit            ; exit routine, modified if XMS, VCPI
  48.  
  49. savedstakoff    dw      ?               ; current saved stack offset
  50. savedstakseg    dw      ?               ; current saved stack segment
  51.  
  52. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  53. ; 16 bit common system code
  54. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  55. ;═════════════════════════════════════════════════════════════════════════════
  56. intreal:                                ; real mode int, load FS and GS here
  57.         pushf
  58. ;-----------------------------------------------------------------------------
  59. callreal:                               ; real mode call, load FS and GS here
  60.         push cs
  61.         push offset icreald
  62.         mov fs,cs:v86r_fs
  63.         mov gs,cs:v86r_gs
  64.         mov eax,cs:v86r_eax
  65.         mov ecx,cs:v86r_ecx
  66.         mov edx,cs:v86r_edx
  67.         mov ebx,cs:v86r_ebx
  68.         mov esi,cs:v86r_esi
  69.         mov edi,cs:v86r_edi
  70.         mov ebp,cs:v86r_ebp
  71. ;-----------------------------------------------------------------------------
  72. icreal:                                 ; real mode int, call, or IRQ
  73.         db 66h,68h              ; PUSH destination addx
  74. icrealm1        dd      ?       ;
  75. icrealm0        db      ?       ; CLI or STI
  76.         retf
  77. ;-----------------------------------------------------------------------------
  78. icreald:                                ; done with real int or call
  79.         cli
  80.         pushf
  81.         pop cs:v86r_flags
  82.         mov cs:v86r_eax,eax
  83.         mov cs:v86r_ecx,ecx
  84.         mov cs:v86r_edx,edx
  85.         mov cs:v86r_ebx,ebx
  86.         mov cs:v86r_esi,esi
  87.         mov cs:v86r_edi,edi
  88.         mov cs:v86r_ebp,ebp
  89.         mov cs:v86r_ds,ds
  90.         mov cs:v86r_es,es
  91.         mov cs:v86r_fs,fs
  92.         mov cs:v86r_gs,gs
  93. icreald2:
  94.         mov ax,cs
  95.         mov ds,ax
  96. icrealm2        label word              ; return to pmode modifiable to JMP
  97. ;-----------------------------------------------------------------------------
  98.         mov ebx,ds:cp_savedstakoff      ; DPMI return to pmode
  99.         mov dx,ds:dp_savedstaksel
  100.         mov edi,offset dp_int3_d
  101.         mov si,ds:_selcode
  102.         mov cx,dx
  103.         mov ax,ds:_seldata
  104.         jmp ds:d_switchaddx
  105. ;-----------------------------------------------------------------------------
  106. VICREAL1D=(($-(icrealm2+2))shl 8)+0ebh
  107. v_icreal1d:                             ; VCPI return to pmode from safe
  108.         mov edi,offset cp_int3_d
  109. ;-----------------------------------------------------------------------------
  110. ; EDI=offset to jump to in code32
  111. v_switchtopmode:                        ; VCPI switch to pmode
  112.         mov ds:v_ss_dest,edi
  113.         mov esi,offset v_ss_cr3
  114.         add esi,ds:_code16a
  115.         mov ax,0de0ch
  116.         int 67h
  117. ;-----------------------------------------------------------------------------
  118. CICREAL1D=(($-(icrealm2+2))shl 8)+0ebh
  119. c_icreal1d:                             ; custom return to pmode from safe
  120.     mov edi,offset cp_int3_d
  121. ;-----------------------------------------------------------------------------
  122. ; EDI=offset in pmode to jump to
  123. c_retpmode:                             ; reenter 32bit pmode
  124.         lgdt fword ptr c_gdt32addx      ; set up pmode GDT and IDT
  125.     lidt fword ptr c_idt32addx
  126.     mov ds:gdt32task[5],89h     ; set task as not busy
  127.         mov eax,cr0                     ; switch to pmode
  128.         or al,1
  129.         mov cr0,eax
  130.         db 0eah
  131.         dw $+4,20h
  132.         mov ax,30h                      ; load task register
  133.         ltr ax
  134.     jmp c_gotopmode
  135. ;═════════════════════════════════════════════════════════════════════════════
  136. int32:                                  ; real mode INT32: EDX=off
  137.         pushad
  138.         push ds es fs gs
  139.         cli
  140.         mov ax,cs
  141.         mov ds,ax
  142.         mov ds:p_cpmodem0,edx
  143.         mov al,[esp+45]
  144.         shr al,1
  145.         and al,1
  146.         add al,0fah
  147.         mov ds:p_cpmodem1,al
  148.         push savedstakoff
  149.         push savedstakseg
  150.         movzx ebx,ds:nextmodestack
  151.         lea eax,[ebx-STAKPMODE*16]
  152.         mov ds:nextmodestack,ax
  153.         add ebx,ds:realstackbase
  154.         mov savedstakseg,ss
  155. int32m0         label   word            ; jump to pmode, modifiable
  156. ;-----------------------------------------------------------------------------
  157.         sub sp,ds:dp_savelen
  158.         mov savedstakoff,sp
  159.         mov ax,ss                       ; DPMI jump to pmode
  160.         mov es,ax
  161.         mov di,sp
  162.         xor al,al
  163.         call d_saveaddx
  164.         mov ax,ds:_seldata
  165.         mov cx,ax
  166.         mov dx,ax
  167.         mov edi,offset p_cpmode0
  168.         mov si,ds:_selcode
  169.         jmp ds:d_switchaddx
  170. ;-----------------------------------------------------------------------------
  171. VINT32=(($-(int32m0+2))shl 8)+0ebh
  172. v_int32:                                ; VCPI call pmode
  173.         push ds:p_cpmodem2
  174.         mov ds:p_cpmodem2,VCPMODED
  175.         mov savedstakoff,sp
  176.         mov edi,offset p_cpmode1
  177.         jmp v_switchtopmode
  178. ;-----------------------------------------------------------------------------
  179. if ($-(int32m0+2)) gt 127
  180.   err
  181. endif
  182. CINT32=(($-(int32m0+2))shl 8)+0ebh
  183. c_int32:                                ; raw/XMS call pmode
  184.         push ds:p_cpmodem2
  185.         mov ds:p_cpmodem2,CCPMODED
  186.         mov savedstakoff,sp
  187.         mov edi,offset p_cpmode1
  188.         jmp c_retpmode
  189. ;═════════════════════════════════════════════════════════════════════════════
  190. int32d0:                                ; DPMI done with pmode call
  191.         mov di,sp
  192.         mov al,1
  193.         call d_saveaddx
  194.         add sp,ds:dp_savelen
  195. ;-----------------------------------------------------------------------------
  196. int32d2:                                ; done from all
  197.         pop savedstakseg
  198.         pop savedstakoff
  199.         add ds:nextmodestack,STAKPMODE*16
  200.         mov bx,ds:v86r_flags
  201.         mov ax,[esp+44]
  202.         and ax,not 8d5h
  203.         and bx,8d5h
  204.         or ax,bx
  205.         mov [esp+44],ax
  206.         pop gs fs es ds
  207.         popad
  208.         iret
  209. ;═════════════════════════════════════════════════════════════════════════════
  210. int32d1:                                ; VCPI done with pmode call
  211.         mov ss,savedstakseg
  212.         pop ds:p_cpmodem2
  213.         jmp int32d2
  214. ;═════════════════════════════════════════════════════════════════════════════
  215. int32d3:                                ; raw/XMS done with pmode call
  216.         mov c_retreal0m0,offset c_sicreal
  217.         mov ax,cs
  218.         mov ds,ax
  219.         movzx esp,savedstakoff
  220.         mov ss,savedstakseg
  221.         pop ds:p_cpmodem2
  222.         jmp int32d2
  223. ;─────────────────────────────────────────────────────────────────────────────
  224. chek_VCPI:                              ; Chek for VCPI
  225.         xor ax,ax
  226.         mov gs,ax
  227.         mov ax,gs:[67h*4]
  228.         or ax,gs:[(67h*4)+2]
  229.         jz short chekVCPIa
  230.         mov ax,0de00h
  231.         int 67h
  232.         or ah,ah
  233.         clc
  234.         jz short chekVCPId
  235. chekVCPIa:
  236.         stc
  237. chekVCPId:
  238.         ret
  239. ;─────────────────────────────────────────────────────────────────────────────
  240. chek_processor:                         ; Detect if current processor 386
  241.         pushf
  242.         xor ah,ah
  243.         push ax
  244.         popf
  245.         pushf
  246.         pop ax
  247.         and ah,0f0h
  248.         cmp ah,0f0h
  249.         je short detectno386
  250.         mov ah,0f0h
  251.         push ax
  252.         popf
  253.         pushf
  254.         pop ax
  255.         and ah,0f0h
  256.         jz short detectno386
  257.         popf
  258.         ret
  259. detectno386:
  260.         mov dx,offset errmsg0
  261.         jmp short exit16err
  262. ;─────────────────────────────────────────────────────────────────────────────
  263. chek_V86:                               ; Chek if already in V86 mode
  264.         smsw ax
  265.         test al,1
  266.         mov dx,offset errmsg2
  267.         jnz short exit16err
  268.         ret
  269. ;─────────────────────────────────────────────────────────────────────────────
  270. pregetlomem:                            ; Get low memory or abort
  271.         add eax,ds:_lomembase
  272.         mov ebx,ds:_lomemtop
  273.         cmp eax,ebx
  274.         ja short pregetlomema
  275.         mov ecx,eax
  276.         xchg eax,ds:_lomembase
  277.         sub ebx,ecx
  278.         cmp ebx,LOWMIN*1024
  279.         jb short pregetlomema
  280.         ret
  281. pregetlomema:
  282.         mov dx,offset errmsg1
  283. ;─────────────────────────────────────────────────────────────────────────────
  284. exit16err:                              ; Exit program with message
  285.         mov ah,9
  286.         int 21h
  287.         jmp exitrout
  288. ;-----------------------------------------------------------------------------
  289. exit:                                   ; Guess what???
  290.         movzx esp,sp
  291.         mov ah,4ch
  292.         mov al,ds:_exitcode
  293.         int 21h
  294. ;═════════════════════════════════════════════════════════════════════════════
  295. start16:                                ; Program begins here
  296.         cli
  297.         cld
  298.         push cs
  299.         pop ds
  300.  
  301.         call chek_processor             ; is it at least a 386¿
  302.  
  303.         mov ax,es                       ; set up a bunch of pointers
  304.         movzx eax,ax
  305.         shl eax,4
  306.         mov ds:_pspa,eax
  307.         mov eax,code16
  308.         shl eax,4
  309.         mov ds:_code16a,eax
  310.         or dword ptr ds:gdt32code16[2],eax
  311.         or dword ptr ds:gdt32data16[2],eax
  312.         mov ebx,code32
  313.         shl ebx,4
  314.         mov ds:_code32a,ebx
  315.         or dword ptr ds:gdt32code32[2],ebx
  316.         or dword ptr ds:gdt32data32[2],ebx
  317.         add dword ptr ds:c_gdt32addx[2],ebx
  318.         mov eax,codeend
  319.         shl eax,4
  320.         sub eax,ebx
  321.         mov ds:_lomembase,eax
  322.         mov ds:realstackbase,eax
  323.         movzx eax,word ptr es:[2]
  324.         shl eax,4
  325.         sub eax,ebx
  326.         mov ds:_lomemtop,eax
  327.  
  328.         mov eax,STAKSIZE*16             ; get stack memory
  329.         call pregetlomem
  330.  
  331.         push es                         ; save PSP seg (DPMI chek kills ES)
  332.         pop fs
  333.  
  334. if DETECTORDER eq 0
  335.         mov ax,1687h                    ; chek for DPMI
  336.         int 2fh
  337.         or ax,ax
  338.         jz d_start
  339.  
  340.         call chek_VCPI                  ; chek for VCPI
  341.         jnc v_start
  342. else
  343.         call chek_VCPI                  ; chek for VCPI
  344.         jnc v_start
  345.  
  346.         mov ax,1687h                    ; chek for DPMI
  347.         int 2fh
  348.         or ax,ax
  349.         jz d_start
  350. endif
  351.  
  352.         call chek_V86                   ; chek for V86 mode
  353.  
  354.         mov ax,4300h                    ; chek for XMS
  355.         int 2fh
  356.         cmp al,80h
  357.         je x_start
  358.  
  359.         jmp c_start                     ; custom system start
  360. ;─────────────────────────────────────────────────────────────────────────────
  361. enableA20:                              ; hardware enable gate A20
  362.         xor ax,ax
  363.         mov fs,ax
  364.         dec ax
  365.         mov gs,ax
  366.         call testA20
  367.         je short enableA20done
  368.         in al,92h                       ; PS/2 A20 enable
  369.         or al,2
  370.         jmp short $+2
  371.         jmp short $+2
  372.         jmp short $+2
  373.         out 92h,al
  374.         call testA20
  375.         je short enableA20done
  376.         call enableA20o1                ; AT A20 enable
  377.         jnz short enableA20wait
  378.         mov al,0d1h
  379.         out 64h,al
  380.         call enableA20o1
  381.         jnz short enableA20wait
  382.         mov al,0dfh
  383.         out 60h,al
  384.         push offset enableA20wait
  385. enableA20o1:
  386.         mov ecx,20000h
  387. enableA20o1l:
  388.         jmp short $+2
  389.         jmp short $+2
  390.         jmp short $+2
  391.         in al,64h
  392.         test al,2
  393.         loopnz enableA20o1l
  394. enableA20done:
  395.         ret
  396. ;-----------------------------------------------------------------------------
  397. enableA20wait:                          ; wait for A20
  398.         mov al,36h
  399.         out 43h,al
  400.         xor al,al
  401.         out 40h,al
  402.         out 40h,al
  403.         mov cx,800h
  404. enableA20waitl0:
  405.         call testA20
  406.         je enableA20done
  407.         in al,40h
  408.         in al,40h
  409.         mov ah,al
  410. enableA20waitl1:
  411.         in al,40h
  412.         in al,40h
  413.         cmp al,ah
  414.         je enableA20waitl1
  415.         loop enableA20waitl0
  416.         mov dx,offset errmsg4
  417.         jmp exit16err
  418. ;-----------------------------------------------------------------------------
  419. testA20:                                ; Test for enabled A20
  420.         mov al,fs:[0]
  421.         mov ah,al
  422.         not al
  423.         mov gs:[10h],al
  424.         cmp ah,fs:[0]
  425.         mov fs:[0],ah
  426.         ret
  427. ;─────────────────────────────────────────────────────────────────────────────
  428. ; BL=low PIC val, BH=high PIC val
  429. setintslots:                            ; set int nums in table to PIC vals
  430.         mov edi,offset ds:intslottbl
  431.         mov cl,8
  432. setintslotsl0:
  433.         mov [di],bl
  434.         inc di
  435.         inc bl
  436.         dec cl
  437.         jnz setintslotsl0
  438.         mov cl,8
  439. setintslotsl1:
  440.         mov [di],bh
  441.         inc di
  442.         inc bh
  443.         dec cl
  444.         jnz setintslotsl1
  445.         ret
  446.  
  447. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  448. ; 16 bit DPMI system data
  449. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  450. d_errmsg0       db      'DPMI host is not 32bit!!!',7,'$'
  451. d_errmsg1       db      'Ran out of DPMI descriptors!!!',7,'$'
  452. d_errmsg2       db      'Couldn''t set DPMI descriptors as needed!!!',7,'$'
  453. d_errmsg3       db      'Couldn''t enter 32bit protected mode!!!',7,'$'
  454.  
  455. d_enterpmode    dw      ?,?             ; DPMI switch to pmode addx
  456. d_pspsel        dw      ?               ; stupid PSP selector
  457. d_oldenvsegsel  dw      ?               ; stupid selector we dont want
  458.  
  459. d_switchaddx    dd      ?               ; switch to pmode addx
  460. d_saveaddx      dd      ?               ; save/restore state addx
  461.  
  462. d_nintoff       dd      offset dp_irq0,offset dp_irq1,offset dp_irq2,offset dp_irq3
  463.                 dd      offset dp_irq4,offset dp_irq5,offset dp_irq6,offset dp_irq7
  464.                 dd      offset dp_irq8,offset dp_irq9,offset dp_irqa,offset dp_irqb
  465.                 dd      offset dp_irqc,offset dp_irqd,offset dp_irqe,offset dp_irqf
  466.                 dd      offset dp_int33,offset dp_int32
  467. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  468. ; 16 bit DPMI system code
  469. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  470. ;═════════════════════════════════════════════════════════════════════════════
  471. d_retreal:                              ; Return to real mode
  472.         mov ax,205h                     ; restore all int vectors needed
  473.         mov edi,17
  474. d_retreall0:
  475.         mov bl,ds:intslottbl[edi]
  476.         lea ebp,[edi*2+edi]
  477.         mov edx,dword ptr ds:dp_ointbuf[ebp*2]
  478.         mov cx,word ptr ds:dp_ointbuf[ebp*2+4]
  479.         int 31h
  480.         sub di,1
  481.         jnc d_retreall0
  482.         jmp short d_exit
  483. ;─────────────────────────────────────────────────────────────────────────────
  484. d_exit16err:                            ; DPMI Exit with error message
  485.         mov ds:v86r_ds,code16
  486.         mov ds:v86r_ah,9
  487.         mov ax,300h
  488.         mov bx,21h
  489.         xor cx,cx
  490.         mov edi,offset ds:v86r_edi
  491.         push ds
  492.         pop es
  493.         int 31h
  494. ;─────────────────────────────────────────────────────────────────────────────
  495. d_exit:                                 ; DPMI exit to real mode
  496.         mov es,d_pspsel                 ; restore env selector
  497.         mov ax,d_oldenvsegsel
  498.         mov es:[2ch],ax
  499.         jmp exit
  500. ;═════════════════════════════════════════════════════════════════════════════
  501. d_start:                                ; Start in a crappy DPMI system
  502.         or ds:_sysbyte0,3               ; set system type DPMI byte
  503.  
  504.         test bl,1                       ; must be 32bit DPMI
  505.         mov dx,offset d_errmsg0
  506.         jz exit16err
  507.  
  508.         mov d_enterpmode[0],di          ; store enter addx
  509.         mov d_enterpmode[2],es
  510.         push word ptr fs:[2ch]          ; preserve old env seg
  511.  
  512.         movzx eax,si                    ; get mem for DPMI blok
  513.         shl eax,4
  514.         call pregetlomem
  515.         shr eax,4
  516.         add ax,code32
  517.         mov es,ax
  518.  
  519.         mov ax,1                        ; switch to pmode
  520.         call dword ptr d_enterpmode
  521.         cli                             ; I don't trust DPMI
  522.         mov dx,offset d_errmsg3
  523.         jc exit16err
  524.         mov ds:v86r_dx,offset d_errmsg1 ; prepare for abort maybe
  525.         pop ax                          ; swap old env seg with selector
  526.         xchg ax,es:[2ch]
  527.         mov d_oldenvsegsel,ax
  528.         mov d_pspsel,es                 ; store stupid selectors
  529.         mov ds:data16sel,ds
  530.         mov ds:code16sel,cs
  531.         mov ds:code16off,offset d_retreal       ; set return to real mode addx
  532.         mov ds:_setirqvect,offset dp_setirqvect ; modify some crap
  533.         mov ds:_getirqvect,offset dp_getirqvect
  534.         mov ds:_setselector,offset dp_setselector
  535.  
  536.         push ds                         ; no more need for PSP
  537.         pop es
  538.         mov ax,3                        ; get selector increment value
  539.         int 31h
  540.         mov bx,ax
  541.         xor ax,ax                       ; get needed selectors
  542.         mov cx,3+SELECTORS
  543.         int 31h
  544.         jc d_exit16err
  545.  
  546.         mov si,ax                       ; set up descriptors
  547.         mov ds:_selcode,ax
  548.         lea ecx,[eax+ebx]
  549.         mov ds:_seldata,cx
  550.         lea ebp,[ecx+ebx]
  551.         mov ds:_selzero,bp
  552.         lea eax,[ebp+ebx]
  553. if SELECTORS ne 0
  554.         mov ds:selectorbase,ax
  555.         mov ds:selectorinc,bx
  556. endif
  557.         mov ds:v86r_dx,offset d_errmsg2
  558.         mov ax,0ch                      ; set descriptors from GDT
  559.         mov bx,si
  560.         mov edi,offset ds:gdt32code32
  561.         or byte ptr [edi+5],60h
  562.         int 31h
  563.         jc d_exit16err
  564.         mov bx,cx
  565.         mov edi,offset ds:gdt32data32
  566.         or byte ptr [edi+5],60h
  567.         int 31h
  568.         jc d_exit16err
  569.         mov bx,bp
  570.         mov edi,offset ds:gdt32zero32
  571.         or byte ptr [edi+5],60h
  572.         int 31h
  573.         jc d_exit16err
  574. if SELECTORS ne 0
  575.         mov bx,ds:selectorbase          ; set up extra allocatable selectors
  576.         mov dx,SELECTORS
  577. d_startl1:
  578.         int 31h
  579.         jc d_exit16err
  580.         add bx,ds:selectorinc
  581.         dec dx
  582.         jnz d_startl1
  583. endif
  584.         mov es,cx                       ; ES, FS, and GS what they should be
  585.         mov fs,cx
  586.         mov gs,bp
  587.  
  588.         mov edi,ds:_lomembase           ; chek and get extended memory
  589.         mov eax,ds:_lomemtop
  590.         sub eax,edi
  591.         cmp eax,48
  592.         mov ds:v86r_dx,offset errmsg1
  593.         jb d_exit16err
  594.         mov ax,500h
  595.         int 31h
  596.         mov edx,es:[edi]
  597.         mov ds:v86r_dx,offset errmsg3
  598.         jmp short d_startf0
  599. d_startl2:
  600.         sub edx,4096
  601.         jnc short d_startf0
  602.         xor edx,edx
  603. d_startf0:
  604.         mov eax,edx
  605.         shr eax,10
  606.         cmp eax,EXTMIN
  607.         jb d_exit16err
  608.         or edx,edx
  609.         jz short d_startf1
  610.         mov cx,dx
  611.         shld ebx,edx,16
  612.         mov ax,501h
  613.         int 31h
  614.         jc d_startl2
  615.         shl ebx,16
  616.         mov bx,cx
  617.         sub ebx,ds:_code32a
  618.         mov ds:_himembase,ebx
  619.         add ebx,edx
  620.         mov ds:_himemtop,ebx
  621. d_startf1:
  622.  
  623.         mov ax,305h                     ; get save/restore state addxs
  624.         int 31h
  625.         mov ds:dp_savelen,ax
  626.         mov dword ptr ds:dp_saveaddx[0],edi
  627.         mov word ptr ds:dp_saveaddx[4],si
  628.         mov word ptr d_saveaddx[0],cx
  629.         mov word ptr d_saveaddx[2],bx
  630.         mov ax,306h                     ; get switch mode addxs
  631.         int 31h
  632.         mov dword ptr ds:dp_switchaddx[0],edi
  633.         mov word ptr ds:dp_switchaddx[4],si
  634.         mov word ptr d_switchaddx[0],cx
  635.         mov word ptr d_switchaddx[2],bx
  636.  
  637.         mov ax,400h                     ; set IRQ handlers to PIC values
  638.         int 31h
  639.         xchg dl,dh
  640.         mov bx,dx
  641.         call setintslots
  642.  
  643.         mov ah,2                        ; backup and set all int vectors
  644.         mov si,ds:_selcode
  645.         mov edi,17
  646. d_startl0:
  647.         mov bl,ds:intslottbl[edi]
  648.         mov al,4
  649.         int 31h
  650.         lea ebp,[edi*2+edi]
  651.         mov dword ptr ds:dp_ointbuf[ebp*2],edx
  652.         mov word ptr ds:dp_ointbuf[ebp*2+4],cx
  653.         mov al,5
  654.         mov edx,d_nintoff[edi*4]
  655.         mov cx,si
  656.         int 31h
  657.         sub di,1
  658.         jnc d_startl0
  659.  
  660.         mov ax,es                       ; set up needed regs & go on to 32bit
  661.         mov ss,ax
  662.         add esp,ds:realstackbase
  663.         mov ds,ax
  664.         push dword ptr cs:_selcode
  665.         push offset p_start
  666.         db 66h,0cbh             ; 32bit RETF
  667.  
  668. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  669. ; 16bit VCPI system data
  670. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  671. v_errmsg0       db      'Incompatible VCPI PIC mappings!!!',7,'$'
  672.  
  673. v_pagedirseg    dw      ?               ; seg of page directory
  674. v_pagebase      dw      0               ; first page of himem (*4)+1000h
  675. v_pagetop       dw      0               ; top page of himem (*4)+1000h
  676.  
  677. v_ss_cr3        dd      ?               ; new CR3 for pmode (physical)
  678. v_ss_gdtaddxptr dw      c_gdt32addx,0   ; ptr to GDT data for pmode
  679. v_ss_idtaddxptr dw      c_idt32addx,0   ; ptr to IDT data for pmode
  680. v_ss_ldtsel     dw      0               ; don't need no stinkin LDTs
  681. v_ss_trsel      dw      30h             ; task state segment selector
  682. v_ss_dest       dd      ?               ; start in pmode EIP
  683.                 dw      20h             ; start in pmode CS
  684. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  685. ; 16bit VCPI system code
  686. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  687. ;═════════════════════════════════════════════════════════════════════════════
  688. v_retreal:                              ; VCPI return to real mode
  689.         movzx edi,exitrout
  690.         mov esi,esp
  691.         sub esi,ds:realstackbase
  692.         mov cx,code16
  693. ;═════════════════════════════════════════════════════════════════════════════
  694. ; EDI=offset to jump to, ESI=real mode stack ptr, CX=real mode DS
  695. v_retreal0:                             ; VCPI go to real mode
  696.         sub esp,8
  697.         push ecx
  698.         push dword ptr ds:v86r_es
  699.         dw 06866h,codeend,0     ; PUSH dword codeend
  700.         push esi
  701.         pushfd
  702.         dw 06866h,code16,0      ; PUSH dword code16
  703.         push edi
  704.         mov ax,gs
  705.         mov ds,ax
  706.         mov ax,0de0ch
  707.         call cs:vp_vcpipmentry
  708. ;─────────────────────────────────────────────────────────────────────────────
  709. v_exit:                                 ; VCPI exit (clean up pages)
  710.         mov es,v_pagedirseg
  711.         mov si,v_pagebase
  712.         mov cx,v_pagetop
  713.         sub cx,si
  714.         jbe short v_exitf0
  715. v_exitl0:
  716.         mov edx,es:[si]
  717.         and dx,0f000h
  718.         mov ax,0de05h
  719.         int 67h
  720.         add si,4
  721.         sub cx,4
  722.         jnz v_exitl0
  723. v_exitf0:
  724.         jmp exit
  725. ;─────────────────────────────────────────────────────────────────────────────
  726. v_exiterr1:                             ; VCPI not enough low mem exit
  727.         mov dx,offset errmsg1
  728.         jmp exit16err
  729. ;═════════════════════════════════════════════════════════════════════════════
  730. v_start:                                ; start continues from VCPI
  731.         or ds:_sysbyte0,2               ; set system type VCPI byte
  732.         mov ds:code16off,offset v_retreal       ; VCPI return to real mode
  733.         mov c_idt32handler[40h],offset vp_int33 ; VCPI safe int handlers
  734.         mov c_idt32handler[44h],offset vp_int32
  735.         mov ds:cp_v86irqintr,offset vp_int33f0  ; VCPI IRQ safe int routine
  736.         mov int32m0,VINT32              ; VCPI real INT32
  737.  
  738.         mov ax,0de0ah                   ; get PIC mappings
  739.         int 67h
  740.         mov bh,cl
  741.         mov dx,offset v_errmsg0         ; chek for compatible PIC mapping
  742.         cmp bl,bh
  743.         je exit16err
  744.         cmp bl,30h
  745.         je exit16err
  746.         cmp bh,30h
  747.         je exit16err
  748.         mov ax,70h                      ; compatible, get highest needed num
  749.         cmp al,bl
  750.         ja short v_startf1
  751.         mov al,bl
  752. v_startf1:
  753.         cmp al,bh
  754.         ja short v_startf2
  755.         mov al,bh
  756. v_startf2:
  757.         add al,7
  758.         mov c_numofintvects,al
  759.         lea eax,[eax*8+7]               ; set limit of IDT
  760.         mov c_idt32addx,ax
  761.         call setintslots                ; set int slots needed
  762.         movzx eax,ax
  763.         add eax,2068h+1
  764.         call pregetlomem                ; allocate TSS, IO bitmap, and IDT
  765.         mov ds:cp_tssesp0ptr,eax
  766.         mov eax,ds:_code16a             ; adjust mode switch structure
  767.         add dword ptr v_ss_gdtaddxptr,eax
  768.         add dword ptr v_ss_idtaddxptr,eax
  769.  
  770.         mov exitrout,offset v_exit      ; set VCPI cleanup exit
  771.  
  772.         mov eax,ds:_lomembase           ; align lomem base on a page
  773.         mov ebx,ds:_code32a
  774.         add ebx,eax
  775.         lea ecx,[ebx+0fffh]
  776.         and ecx,0fffff000h
  777.         sub ebx,ecx
  778.         sub eax,ebx
  779.         mov ds:_lomembase,eax
  780.         mov ebp,ds:_lomemtop            ; get available low memory
  781.         sub ebp,eax
  782.         sub ebp,LOWMIN*1024             ; die if not enough
  783.         jc v_exiterr1
  784.         cmp ebp,8192
  785.         jb v_exiterr1
  786.  
  787.         shld eax,ecx,28                 ; get segment and clear all pages
  788.         mov v_pagedirseg,ax
  789.         mov es,ax
  790.         xor di,di
  791.         mov cx,2048
  792.         xor eax,eax
  793.         rep stos dword ptr es:[di]
  794.         mov di,1000h                    ; get VCPI pmode interface
  795.         mov esi,offset ds:gdt32vcpi
  796.         mov ax,0de01h
  797.         int 67h
  798.         mov dword ptr ds:vp_vcpipmentry,ebx
  799.  
  800.         mov v_pagebase,di               ; set up and go through allocation
  801.         mov v_pagetop,di
  802.         movzx eax,di
  803.         sub eax,1000h
  804.         shl eax,10
  805.         sub eax,ds:_code32a
  806.         mov ds:_himembase,eax
  807.         mov ebx,8192
  808. v_startl2:
  809.         mov ax,0de04h
  810.         int 67h
  811.         or ah,ah
  812.         jnz short v_startl2d
  813.         test di,0fffh
  814.         jnz short v_startf4
  815.         add ebx,4096
  816.         cmp ebx,ebp
  817.         jbe short v_startf4
  818.         mov v_pagetop,di
  819.         mov ax,0de05h
  820.         int 67h
  821.         jmp v_exiterr1
  822. v_startf4:
  823.         and dx,0f000h
  824.         or dl,7
  825.         mov es:[di],edx
  826.         add di,4
  827.         jnc v_startl2
  828. v_startl2d:
  829.         mov v_pagetop,di
  830.         lea si,[di-1000h]
  831.         movzx eax,si
  832.         shl eax,10
  833.         sub eax,ds:_code32a
  834.         mov ds:_himemtop,eax
  835.         sub di,v_pagebase
  836.         cmp di,EXTMIN
  837.         mov dx,offset errmsg3
  838.         jb exit16err
  839.         add ds:_lomembase,ebx
  840.  
  841.         movzx ebx,v_pagedirseg          ; set up physical addresses
  842.         shr ebx,8
  843.         mov eax,es:[ebx*4+1000h]
  844.         mov v_ss_cr3,eax
  845.         xor di,di
  846. v_startl3:
  847.         inc ebx
  848.         mov eax,es:[ebx*4+1000h]
  849.         and ax,0f000h
  850.         or al,7
  851.         stos dword ptr es:[di]
  852.         sub si,1000h
  853.         ja v_startl3
  854.  
  855.         mov edi,offset c_startf1        ; offset to jump to in pmode
  856.         mov ebx,ds:cp_tssesp0ptr
  857.         jmp v_switchtopmode             ; duh?
  858.  
  859. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  860. ; 16 bit XMS system data
  861. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  862. x_calladdx      dd      ?               ; XMS driver addx
  863. x_handle        dw      0fedch          ; XMS handle of extended memory
  864. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  865. ; 16 bit XMS system code
  866. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  867. ;─────────────────────────────────────────────────────────────────────────────
  868. x_exit:                                 ; XMS exit (clean up allocation)
  869.         mov ax,cs
  870.         mov ds,ax
  871.         mov dx,x_handle
  872.         mov ah,0dh
  873.         call x_calladdx
  874.         mov ah,0ah
  875.         call x_calladdx
  876.         jmp exit
  877. ;─────────────────────────────────────────────────────────────────────────────
  878. x_exiterr5:                             ; exit with error message 5
  879.         mov dx,offset errmsg5
  880.         jmp exit16err
  881. ;═════════════════════════════════════════════════════════════════════════════
  882. x_start:                                ; start in an XMS system
  883.         or ds:_sysbyte0,1               ; set system type XMS byte
  884.  
  885.         mov ax,4310h                    ; get XMS driver addx
  886.         int 2fh
  887.         mov word ptr x_calladdx[0],bx
  888.         mov word ptr x_calladdx[2],es
  889.  
  890.         mov ah,3                        ; XMS enable A20
  891.         call x_calladdx
  892.         or ax,ax
  893.         mov dx,offset errmsg4
  894.         jz exit16err
  895.  
  896.         mov ah,8                        ; chek and get extended memory
  897.         call x_calladdx
  898.         sub ax,64
  899.         jnc short x_startf0
  900.         xor ax,ax
  901. x_startf0:
  902.         cmp ax,EXTMIN
  903.         mov dx,offset errmsg3
  904.         jb exit16err
  905.         mov dx,ax
  906.         movzx ecx,ax
  907.         shl ecx,10
  908.         mov ah,9
  909.         call x_calladdx
  910.         or ax,ax
  911.         jz x_exiterr5
  912.         mov x_handle,dx
  913.         mov exitrout,offset x_exit
  914.         mov ah,0ch
  915.         call x_calladdx
  916.         or ax,ax
  917.         jz x_exiterr5
  918.         shrd eax,edx,16
  919.         mov ax,bx
  920.         sub eax,ds:_code32a
  921.         mov ds:_himembase,eax
  922.         add eax,ecx
  923.         mov ds:_himemtop,eax
  924.  
  925.         jmp c_startf0                   ; go on to custom start
  926.  
  927. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  928. ; 16 bit custom system data
  929. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  930. c_idt16addx     dw      3ffh, 0,0       ; default real mode IDT addx&limit
  931. c_idt32addx     dw      3bfh, ?,?       ; 32bit IDT addx&limit
  932. c_gdt32addx     dw      04fh+SELECTORS*8; 32bit GDT addx&limit
  933.                 dd      offset gdt32    ;
  934.  
  935. c_numofintvects db      77h             ; number of int vects needed -1
  936. c_idt32handler  dd      offset cp_irq0,offset cp_irq1,offset cp_irq2,offset cp_irq3
  937.                 dd      offset cp_irq4,offset cp_irq5
  938.                 dd      offset cp_irq6,offset cp_irq7,offset cp_irq8,offset cp_irq9
  939.                 dd      offset cp_irqa,offset cp_irqb
  940.                 dd      offset cp_irqc,offset cp_irqd,offset cp_irqe,offset cp_irqf
  941.                 dd      offset cp_int33,offset cp_int32,offset cp_int31
  942.                 dd      offset cp_exc0,offset cp_exc1,offset cp_exc2,offset cp_exc3
  943.                 dd      offset cp_exc4,offset cp_exc5
  944.                 dd      offset cp_exc6,offset cp_exc7
  945. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  946. ; 16 bit custom system code
  947. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  948. ;═════════════════════════════════════════════════════════════════════════════
  949. c_irqreal:                              ; real mode IRQ
  950.         pushf
  951.         push cs
  952.         push offset icreald2
  953.         jmp icreal
  954. ;-----------------------------------------------------------------------------
  955. c_retreal1:                             ; load some real mode stuff & exit
  956.         mov ax,codeend
  957.         mov ss,ax
  958.         mov esp,STAKSIZE*10h
  959.         jmp exitrout
  960. ;═════════════════════════════════════════════════════════════════════════════
  961. c_retreal0:                             ; load real mode IDT and set PE=0
  962.         mov ax,28h
  963.         mov ds,ax
  964.         mov es,ax
  965.         mov fs,ax
  966.         mov gs,ax
  967.         mov ss,ax
  968.         lidt fword ptr c_idt16addx
  969.         mov eax,cr0
  970.         and al,0feh
  971.         mov cr0,eax
  972.         db 0eah                 ; JMP FAR PTR c_retreal0m0
  973. c_retreal0m0    dw c_sicreal,code16
  974. ;-----------------------------------------------------------------------------
  975. c_sicreal:                              ; safe real mode int or call
  976.         mov ax,codeend
  977.         mov ss,ax
  978.         mov ds,cs:v86r_ds
  979.         mov es,cs:v86r_es
  980.         db 0eah                 ; JMP FAR PTR c_sicrealm0
  981. c_sicrealm0     dw      ?,code16;
  982. ;═════════════════════════════════════════════════════════════════════════════
  983. c_retreal:                              ; return to real mode
  984.         mov c_retreal0m0,offset c_retreal1
  985.         mov esp,STAKSIZE*10h
  986.         jmp c_retreal0
  987. ;═════════════════════════════════════════════════════════════════════════════
  988. c_start:                                ; custom only start
  989.         call enableA20                  ; enable that stupid A20 thingy
  990.  
  991.         mov ah,88h                      ; chek and get extended mem
  992.         int 15h
  993.         cmp ax,EXTMIN
  994.         mov dx,offset errmsg3
  995.         jb exit16err
  996.         movzx eax,ax
  997.         shl eax,10
  998.         mov ebx,100000h
  999.         sub ebx,ds:_code32a
  1000.         mov ds:_himembase,ebx
  1001.         add eax,ebx
  1002.         mov ds:_himemtop,eax
  1003. ;═════════════════════════════════════════════════════════════════════════════
  1004. c_startf0:                              ; start continues from custom or XMS
  1005.         mov int32m0,CINT32              ; raw/XMS real INT32
  1006.         mov eax,2428h                   ; allocate TSS, IO bitmap, and IDT
  1007.         call pregetlomem
  1008.         mov ebx,eax
  1009.  
  1010.         lgdt fword ptr c_gdt32addx      ; switch to pmode
  1011.         mov eax,cr0
  1012.         or al,1
  1013.         mov cr0,eax
  1014.         db 0eah
  1015.         dw $+4,20h
  1016. ;-----------------------------------------------------------------------------
  1017. ; EBX->TSS
  1018. c_startf1:                              ; in 16bit pmode
  1019.         mov ax,28h                      ; set up segregs
  1020.         mov ds,ax
  1021.         mov al,18h
  1022.         mov gs,ax
  1023.         mov al,10h
  1024.         mov es,ax
  1025.         mov fs,ax
  1026.         mov ss,ax
  1027.         mov esp,STAKSIZE*16
  1028.         add esp,ds:realstackbase
  1029.  
  1030.         mov word ptr v_ss_dest[4],8     ; VCPI enter 32bit pmode from now on
  1031.         lea eax,[ebx+4]                 ; addx of ESP0 in TSS
  1032.         mov ds:cp_tssesp0ptr,eax
  1033.         mov ebp,ds:_code32a             ; TSS location in mem to GDT
  1034.         lea eax,[ebx+ebp]
  1035.         mov ecx,offset ds:gdt32task     ; set up task
  1036.         or dword ptr ds:[ecx+2],eax
  1037.         mov byte ptr ds:[ecx+5],89h
  1038.         mov cx,30h
  1039.         ltr cx
  1040.         add eax,2068h                   ; set up IDT
  1041.         mov ecx,offset c_idt32addx
  1042.         mov dword ptr [ecx+2],eax
  1043.         lidt fword ptr [ecx]
  1044.  
  1045.         mov dword ptr es:[ebx+8],10h    ; set up TSS stuff (EBX->TSS)
  1046.         mov edi,104
  1047.         mov es:[ebx+102],di
  1048.         mov word ptr es:[ebx+100],0
  1049.         add edi,ebx                     ; fill IO bitmap with 0
  1050.         xor eax,eax
  1051.         mov ecx,800h
  1052.         rep stos dword ptr es:[edi]
  1053.  
  1054.         mov ds:cp_idt32ptr,edi          ; set up blank IDT entries
  1055.         movzx esi,c_numofintvects
  1056. c_startl0:
  1057.         mov dword ptr es:[edi+esi*8],80000h+offset cp_excf
  1058.         mov dword ptr es:[edi+esi*8+4],8e00h
  1059.         sub si,1
  1060.         jnc c_startl0
  1061.         mov si,1ah                      ; necessary IDT entries
  1062. c_startl1:
  1063.         movzx ebp,ds:intslottbl[esi]
  1064.         mov eax,c_idt32handler[esi*4]
  1065. c_startl1c:
  1066.         mov es:[edi+ebp*8],ax
  1067.         sub si,1
  1068.         jnc c_startl1
  1069.  
  1070.         mov edi,offset p_start          ; set up regs & go on to 32bit
  1071.     mov ax,10h
  1072.         mov ds,ax
  1073. ;-----------------------------------------------------------------------------
  1074. c_gotopmode:                ; jump to 32bit pmode
  1075.         pushfd                          ; set eflags: NT=0, IOPL=3
  1076.         pop eax
  1077.         and ah,0bfh
  1078.         or ah,30h
  1079.         push eax
  1080.         popfd
  1081.         dw 6866h,8,0            ; PUSH dword 8
  1082.     push edi
  1083.         db 66h,0cbh             ; 32bit RETF
  1084.  
  1085. code16  ends
  1086.  
  1087. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1088. ; 32bit pmode code
  1089. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1090. code32  segment para public use32
  1091.         assume cs:code32, ds:code32
  1092.         org 0
  1093.  
  1094. extrn   _main:near
  1095.  
  1096. public  _exit, _ret, _getmem, _getlomem, _gethimem, _lomemsize, _himemsize
  1097. public  _getirqmask, _setirqmask, _getselector, _freeselector, _rmpmirqset
  1098. public  _rmpmirqfree
  1099.  
  1100. public  v86r_eax, v86r_ebx, v86r_ecx, v86r_edx, v86r_esi, v86r_edi, v86r_ebp
  1101. public  v86r_ax, v86r_bx, v86r_cx, v86r_dx, v86r_si, v86r_di, v86r_bp
  1102. public  v86r_al, v86r_ah, v86r_bl, v86r_bh, v86r_cl, v86r_ch, v86r_dl, v86r_dh
  1103. public  v86r_ds, v86r_es, v86r_fs, v86r_gs
  1104. public  _selcode, _seldata, _selzero, _lomembase, _lomemtop, _himembase
  1105. public  _himemtop, _pspa, _code16a, _code32a, _getirqvect, _setirqvect
  1106. public  _sysbyte0, _setselector, _exitcode
  1107. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1108. ; 32 bit common system data
  1109. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1110. _lomembase      dd      ?               ; low mem base for allocation
  1111. _lomemtop       dd      ?               ; top of low mem
  1112. _himembase      dd      0               ; high mem base for allocation
  1113. _himemtop       dd      0               ; top of high mem
  1114. _pspa           dd      ?               ; offset of start of PSP from 0
  1115. _code16a        dd      ?               ; offset of start of 16bit code from 0
  1116. _code32a        dd      ?               ; offset of start of 32bit code from 0
  1117. _selcode        dw      8               ; code segment selector
  1118. _seldata        dw      10h             ; data segment alias for code
  1119. _selzero        dw      18h             ; data segment starting at 0:0
  1120. _sysbyte0       db      0               ; system bits:
  1121.                                         ;  0-1: 0=raw, 1=XMS, 2=VCPI, 3=DPMI
  1122. _exitcode       db      0               ; exit code for int21h ah=4ch
  1123.  
  1124. align 4
  1125. _getirqvect     dd      cp_getirqvect   ; get IRQ handler offset routine addx
  1126. _setirqvect     dd      cp_setirqvect   ; set IRQ handler offset routine addx
  1127. _setselector    dd      cp_setselector  ; set a selector addx offset addx
  1128.  
  1129. gdt32           dq      0
  1130. gdt32code32     db      0ffh,0ffh,0,0,0,9ah,0cfh,0
  1131. gdt32data32     db      0ffh,0ffh,0,0,0,92h,0cfh,0
  1132. gdt32zero32     db      0ffh,0ffh,0,0,0,92h,0cfh,0
  1133. gdt32code16     db      0ffh,0ffh,0,0,0,9ah,0,0
  1134. gdt32data16     db      0ffh,0ffh,0,0,0,92h,0,0
  1135. gdt32task       db      0ffh,0ffh,0,0,0,89h,0,0
  1136. gdt32vcpi       dq      3 dup(?)
  1137. if SELECTORS ne 0
  1138. gdt32free       db      SELECTORS dup(0ffh,0ffh,0,0,0,92h,0cfh,0)
  1139. endif
  1140.  
  1141. v86r_edi        label   dword           ; vregs for pmode<>real communication
  1142. v86r_di         dw      ?, ?            ;  needs to stay this way cuz its a
  1143. v86r_esi        label   dword           ;  stupid DPMI structure thingy
  1144. v86r_si         dw      ?, ?
  1145. v86r_ebp        label   dword
  1146. v86r_bp         dw      ?, ?
  1147.                 dd      0
  1148. v86r_ebx        label   dword
  1149. v86r_bx         label   word
  1150. v86r_bl         db      ?
  1151. v86r_bh         db      ?, ?,?
  1152. v86r_edx        label   dword
  1153. v86r_dx         label   word
  1154. v86r_dl         db      ?
  1155. v86r_dh         db      ?, ?,?
  1156. v86r_ecx        label   dword
  1157. v86r_cx         label   word
  1158. v86r_cl         db      ?
  1159. v86r_ch         db      ?, ?,?
  1160. v86r_eax        label   dword
  1161. v86r_ax         label   word
  1162. v86r_al         db      ?
  1163. v86r_ah         db      ?, ?,?
  1164. v86r_flags      dw      ?
  1165. v86r_es         dw      ?
  1166. v86r_ds         dw      ?
  1167. v86r_fs         dw      ?
  1168. v86r_gs         dw      ?
  1169.                 dd      0,0
  1170.  
  1171. oint1bvect      dd      ?               ; old real int 1bh vector (ctrl+break)
  1172. oint32vect      dd      ?               ; old real int 32h vector
  1173. oirqmask        dw      ?               ; old port 21h and 0a1h masks
  1174. intslottbl      db      8,9,0ah,0bh,0ch,0dh,0eh,0fh,70h,71h,72h,73h,74h,75h,76h,77h
  1175.                 db      33h,32h,31h,0,1,2,3,4,5,6,7
  1176.  
  1177. if SELECTORS ne 0
  1178. selectorbase    dw      50h
  1179. selectorinc     dw      8
  1180. selectorfree    db      SELECTORS dup(0)
  1181. endif
  1182.  
  1183. code16off       dw      c_retreal       ; offset in 16bit of exit function
  1184. code16sel       dw      20h             ; 16bit pmode code selector
  1185. data16sel       dw      28h             ; 16bit pmode data selector
  1186.  
  1187. nextmodestack   dw      (STAKSIZE-STAKMAIN)*16  ; stack for next mode switch
  1188. realstackbase   dd      ?               ; linear ptr to beginning of codeend
  1189.  
  1190. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1191. ; 32 bit common system code
  1192. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1193. ;═════════════════════════════════════════════════════════════════════════════
  1194. p_cpmode2:                ; call pmode from V86
  1195.         mov gs,cx
  1196.         mov cl,10h
  1197.         mov ds,cx
  1198.         mov es,cx
  1199.         mov fs,cx
  1200.         sub nextmodestack,STAKPMODE*16
  1201.     push p_cpmodem2
  1202.     mov p_cpmodem2,V86CPMODED
  1203.         mov eax,[esp+22]
  1204.     mov p_cpmodem0,eax
  1205.         mov al,[esp+43]
  1206.     shr al,1
  1207.     and al,1
  1208.     add al,0fah
  1209.     mov p_cpmodem1,al
  1210.         jmp short p_cpmode
  1211. ;═════════════════════════════════════════════════════════════════════════════
  1212. p_cpmode1:                              ; call pmode, load all
  1213.         mov esp,ebx
  1214.         mov ax,10h
  1215.         mov ds,ax
  1216.         mov es,ax
  1217.         mov ss,ax
  1218. ;-----------------------------------------------------------------------------
  1219. p_cpmode0:                              ; call pmode, load FS and GS
  1220.         mov fs,_seldata
  1221.         mov gs,_selzero
  1222. ;-----------------------------------------------------------------------------
  1223. p_cpmode:                               ; call pmode routine from real
  1224.         push offset p_cpmoded
  1225.         cld
  1226.         mov eax,v86r_eax
  1227.         mov ecx,v86r_ecx
  1228.         mov edx,v86r_edx
  1229.         mov ebx,v86r_ebx
  1230.         mov esi,v86r_esi
  1231.         mov edi,v86r_edi
  1232.         mov ebp,v86r_ebp
  1233.         db 68h                  ; PUSH destination address
  1234. p_cpmodem0      dd      ?       ;
  1235. p_cpmodem1      db      ?       ; CLI or STI
  1236.         ret
  1237. ;-----------------------------------------------------------------------------
  1238. p_cpmoded:                              ; call to pmode done
  1239.         cli
  1240.         pushf
  1241.         pop v86r_flags
  1242.         mov v86r_eax,eax
  1243.         mov v86r_ecx,ecx
  1244.         mov v86r_edx,edx
  1245.         mov v86r_ebx,ebx
  1246.         mov v86r_esi,esi
  1247.         mov v86r_edi,edi
  1248.         mov v86r_ebp,ebp
  1249.         mov ecx,_code16a
  1250. p_cpmodem2        label word            ; return to real, modifiable to JMP
  1251. ;-----------------------------------------------------------------------------
  1252.         movzx ebx,gs:savedstakoff[ecx]  ; DPMI return to real mode
  1253.         mov dx,gs:savedstakseg[ecx]
  1254.         mov ax,code16
  1255.         mov cx,dx
  1256.         mov si,ax
  1257.         mov edi,offset int32d0
  1258.         jmp dp_switchaddx
  1259. ;-----------------------------------------------------------------------------
  1260. VCPMODED=(($-(p_cpmodem2+2))shl 8)+0ebh
  1261. p_cpmoded2:                             ; VCPI done with pmode
  1262.         movzx esi,gs:savedstakoff[ecx]
  1263.         mov cx,code16
  1264.         mov edi,offset int32d1
  1265.         db 0eah                 ; 16bit JMP FAR 20h:v_retreal0
  1266.         dw v_retreal0,0,20h     ;
  1267. ;-----------------------------------------------------------------------------
  1268. CCPMODED=(($-(p_cpmodem2+2))shl 8)+0ebh
  1269. p_cpmoded3:                             ; raw/XMS done with pmode
  1270.         mov gs:c_retreal0m0[ecx],offset int32d3
  1271.         db 0eah                 ; 16bit JMP FAR 20h:c_retreal0
  1272.         dw c_retreal0,0,20h     ;
  1273. ;-----------------------------------------------------------------------------
  1274. if ($-(p_cpmodem2+2)) gt 127
  1275.   err
  1276. endif
  1277. V86CPMODED=(($-(p_cpmodem2+2))shl 8)+0ebh
  1278. p_cpmoded4:                ; V86 done with pmode
  1279.     pop p_cpmodem2
  1280.         jmp cp_int3_d3
  1281. ;═════════════════════════════════════════════════════════════════════════════
  1282. p_start:                                ; common 32bit start
  1283.         mov eax,gs:[1bh*4]              ; neutralize crtl+break
  1284.         mov oint1bvect,eax
  1285.         db 65h,67h,0c7h,6       ; MOV DWORD PTR GS:[1bh*4],code16:nullint
  1286.         dw 1bh*4,nullint,code16 ;
  1287.         mov eax,gs:[32h*4]              ; set up for new real mode INT32
  1288.         mov oint32vect,eax
  1289.         db 65h,67h,0c7h,6       ; MOV DWORD PTR GS:[32h*4],code16:int32
  1290.         dw 32h*4,int32,code16   ;
  1291.         in al,21h                       ; save old PIC masks
  1292.         mov ah,al
  1293.         in al,0a1h
  1294.         mov oirqmask,ax
  1295.         jmp _main                       ; go to main code
  1296.  
  1297. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1298. ; Allocate any mem, (first cheks low, then high)
  1299. ; In:
  1300. ;   EAX - size requested
  1301. ; Out:
  1302. ;   CF=0 - memory allocated
  1303. ;   CF=1 - not enough mem
  1304. ;   EAX - linear pointer to mem or ?
  1305. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1306. _getmem:
  1307.         push eax
  1308.         call _getlomem
  1309.         jnc short getmemd
  1310.         pop eax
  1311.         jmp short _gethimem
  1312. getmemd:
  1313.         add esp,4
  1314. _ret:                                   ; generic RET instruction
  1315.         ret
  1316. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1317. ; Allocate some low mem
  1318. ; In:
  1319. ;   EAX - size requested
  1320. ; Out:
  1321. ;   CF=0 - memory allocated
  1322. ;   CF=1 - not enough mem
  1323. ;   EAX - linear pointer to mem or ?
  1324. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1325. _getlomem:
  1326.         add eax,_lomembase
  1327.         cmp eax,_lomemtop
  1328.         ja short getmemerr
  1329.         xchg eax,_lomembase
  1330.         clc
  1331.         ret
  1332. getmemerr:
  1333.         stc
  1334.         ret
  1335. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1336. ; Allocate some high mem
  1337. ; In:
  1338. ;   EAX - size requested
  1339. ; Out:
  1340. ;   CF=0 - memory allocated
  1341. ;   CF=1 - not enough mem
  1342. ;   EAX - linear pointer to mem or ?
  1343. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1344. _gethimem:
  1345.         add eax,_himembase
  1346.         cmp eax,_himemtop
  1347.         ja short getmemerr
  1348.         xchg eax,_himembase
  1349.         clc
  1350.         ret
  1351. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1352. ; Get amount of free low mem
  1353. ; Out:
  1354. ;   EAX - number of bytes free
  1355. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1356. _lomemsize:
  1357.         mov eax,_lomemtop
  1358.         sub eax,_lomembase
  1359.         ret
  1360. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1361. ; Get amount of free high mem
  1362. ; Out:
  1363. ;   EAX - number of bytes free
  1364. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1365. _himemsize:
  1366.         mov eax,_himemtop
  1367.         sub eax,_himembase
  1368.         ret
  1369. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1370. ; Get status of IRQ mask bit
  1371. ; In:
  1372. ;   BL - IRQ num (0-15)
  1373. ; Out:
  1374. ;   AL - status: 0=enabled, 1=disabled
  1375. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1376. _getirqmask:
  1377.         push ax
  1378.         in al,0a1h
  1379.         mov ah,al
  1380.         in al,21h
  1381.         xchg cl,bl
  1382.         shr ax,cl
  1383.         xchg cl,bl
  1384.         and al,1
  1385.         mov [esp],al
  1386.         pop ax
  1387.         ret
  1388. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1389. ; Set status of IRQ mask bit
  1390. ; In:
  1391. ;   BL - IRQ num (0-15)
  1392. ;   AL - status: 0=enabled, 1=disabled
  1393. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1394. _setirqmask:
  1395.         push ax bx cx dx
  1396.         mov cl,bl
  1397.         mov bx,0fffeh
  1398.         movzx dx,al
  1399.         rol bx,cl
  1400.         shl dx,cl
  1401.         in al,0a1h
  1402.         mov ah,al
  1403.         in al,21h
  1404.         and ax,bx
  1405.         or ax,dx
  1406.         out 21h,al
  1407.         mov al,ah
  1408.         out 0a1h,al
  1409.         pop dx cx bx ax
  1410.         ret
  1411. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1412. ; Set a real mode IRQ vect to redirect to pmode
  1413. ; In:
  1414. ;   BL - IRQ number
  1415. ;   EDX - offset of IRQ handler
  1416. ;   EDI -> 21 byte buffer for code stub created
  1417. ; Out:
  1418. ;   EAX - old seg:off of real mode IRQ handler
  1419. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1420. rmpmirqsetd0:
  1421. db 66h,52h              ; PUSH EDX
  1422. db 66h,0bah,?,?,?,?     ; MOV EDX,?
  1423. db 0cdh,32h             ; INT 32h
  1424. db 66h,5ah              ; POP EDX
  1425. db 0cfh                 ; IRET
  1426. db 9ch                  ; PUSHFD
  1427. db 0eh                  ; PUSH CS
  1428. db 0e8h,?,?,?,?         ; CALL ?
  1429. db 0c3h                 ; RET
  1430. ;-----------------------------------------------------------------------------
  1431. _rmpmirqset:
  1432.         push esi edi
  1433.         mov esi,offset rmpmirqsetd0
  1434.         lea eax,[edi+13]
  1435.         mov [esi+4],eax
  1436.         add eax,7
  1437.         sub eax,edx
  1438.         neg eax
  1439.         mov [esi+16],eax
  1440.         mov eax,edi
  1441.         movsd
  1442.         movsd
  1443.         movsd
  1444.         movsd
  1445.         movsd
  1446.         movsb
  1447.         add eax,_code32a
  1448.         shl eax,12
  1449.         shr ax,12
  1450.         movzx edi,bl
  1451.         cmp edi,8
  1452.         jb short rmpmirqsetf0
  1453.         add edi,60h
  1454. rmpmirqsetf0:
  1455.         xchg eax,gs:[edi*4+20h]
  1456.         pop edi esi
  1457.         ret
  1458. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1459. ; Reset a real more IRQ vect back to normal (just sets real mode IRQ vect)
  1460. ; In:
  1461. ;   BL - IRQ number
  1462. ;   EAX - seg:off of real mode IRQ handler
  1463. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1464. _rmpmirqfree:
  1465.         push ebx
  1466.         movzx ebx,bl
  1467.         cmp bl,8
  1468.         jb short rmpmirqfreef0
  1469.         add bl,60h
  1470. rmpmirqfreef0:
  1471.         mov gs:[ebx*4+20h],eax
  1472.         pop ebx
  1473.         ret
  1474. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1475. ; Allocate a selector
  1476. ; Out:
  1477. ;   CF=1 - selector not allocated
  1478. ;   CF=0 - selector allocated
  1479. ;   AX - 4G data selector or ?
  1480. ; Notes:
  1481. ;   The selector returned is for a 4G r/w data segment with an undefined base
  1482. ;    address.
  1483. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1484. _getselector:
  1485. if SELECTORS eq 0
  1486.         stc
  1487.         ret
  1488. else
  1489.         push ecx edi
  1490.         mov edi,offset selectorfree
  1491.         mov ecx,SELECTORS
  1492.         mov al,0
  1493.         repne scasb
  1494.         jne short getselectorf0
  1495.         mov byte ptr [edi-1],1
  1496.         sub ecx,SELECTORS-1
  1497.         neg ecx
  1498.         imul cx,selectorinc
  1499.         mov ax,selectorbase
  1500.         add ax,cx
  1501.         clc
  1502.         jmp short getselectorf1
  1503. getselectorf0:
  1504.         stc
  1505. getselectorf1:
  1506.         pop edi ecx
  1507.         ret
  1508. endif
  1509. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1510. ; Free an allocated selector
  1511. ; In:
  1512. ;   AX - selector
  1513. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1514. _freeselector:
  1515. if SELECTORS ne 0
  1516.         push eax dx
  1517.         sub ax,selectorbase
  1518.         xor dx,dx
  1519.         div selectorinc
  1520.         movzx eax,ax
  1521.         mov selectorfree[eax],0
  1522.         pop dx eax
  1523. endif
  1524.         ret
  1525. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1526. ; Exit to real mode
  1527. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1528. _exit:
  1529.         cli
  1530.         mov eax,oint1bvect              ; restore ctrl+break
  1531.         mov gs:[1bh*4],eax
  1532.         mov eax,oint32vect              ; restore real mode int 32h vector
  1533.         mov gs:[32h*4],eax
  1534.         mov ax,oirqmask                 ; restore PIC masks
  1535.         out 0a1h,al
  1536.         mov al,ah
  1537.         out 21h,al
  1538.         push code16sel                  ; go to 16bit pmode exit code
  1539.         push code16off
  1540.         mov ds,data16sel
  1541.         db 66h,0cbh             ; 16bit RETF
  1542.  
  1543. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1544. ; 32 bit DPMI system data
  1545. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1546. dp_switchaddx   df      ?               ; switch to real mode addx
  1547. dp_saveaddx     df      ?               ; save/restore state addx
  1548. dp_savelen      dw      0,0             ; length of state buffer
  1549. dp_savedstaksel dw      ?               ; current saved stack selector
  1550.  
  1551. dp_ointbuf      df      18 dup(?)       ; saved interrupt addx buffer
  1552. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1553. ; 32 bit DPMI system code
  1554. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1555. ;═════════════════════════════════════════════════════════════════════════════
  1556. dp_int32:                               ; DPMI INT32/34: CX:DX=seg:off
  1557.         pushad
  1558.         shl ecx,16
  1559.         mov cx,dx
  1560.         mov bp,offset callreal
  1561.         mov dl,1
  1562.         jmp short dp_int3_
  1563. ;═════════════════════════════════════════════════════════════════════════════
  1564. dp_int33:                               ; DPMI INT33/35: AL=int num
  1565.         pushad
  1566.         movzx eax,al
  1567.         mov ecx,gs:[eax*4]
  1568.         mov bp,offset intreal
  1569.         xor dl,dl
  1570. ;-----------------------------------------------------------------------------
  1571. dp_int3_:                               ; DPMI int or call to real mode
  1572.         mov ax,900h
  1573.         int 31h
  1574.         push ax
  1575.         and al,dl
  1576.         add al,0fah
  1577.         mov ebx,_code16a
  1578.         mov gs:icrealm0[ebx],al
  1579.         mov gs:icrealm1[ebx],ecx
  1580.         push cp_savedstakoff
  1581.         push dp_savedstaksel
  1582.         movzx ebx,nextmodestack
  1583.         lea eax,[ebx-STAKRMODE*16]
  1584.         mov nextmodestack,ax
  1585.         mov ax,ss
  1586.         mov es,ax
  1587.         sub esp,dword ptr dp_savelen
  1588.         mov edi,esp
  1589.         xor al,al
  1590.         call dp_saveaddx
  1591.         mov cp_savedstakoff,esp
  1592.         mov dp_savedstaksel,ss
  1593.         mov dx,codeend
  1594.         mov ax,v86r_ds
  1595.         mov cx,v86r_es
  1596.         movzx edi,bp
  1597.         mov si,code16
  1598.         jmp dp_switchaddx
  1599. ;-----------------------------------------------------------------------------
  1600. dp_int3_d:                              ; done with real mode int or call
  1601.         mov edi,esp
  1602.         mov al,1
  1603.         call dp_saveaddx
  1604.         add esp,dword ptr dp_savelen
  1605.         pop dp_savedstaksel
  1606.         pop cp_savedstakoff
  1607.         add nextmodestack,STAKRMODE*16
  1608.         mov bx,v86r_flags
  1609.         pop ax
  1610.         int 31h
  1611.         mov ax,ds
  1612.         mov es,ax
  1613.         mov fs,ax
  1614.         mov gs,_selzero
  1615.         jmp cp_int3_d2
  1616. ;═════════════════════════════════════════════════════════════════════════════
  1617. ; DPMI IRQ redirectors (needed to make all IRQ vector selectors = CS)
  1618. dp_irq0:
  1619.         jmp cs:dp_ointbuf[0]
  1620. dp_irq1:
  1621.         jmp cs:dp_ointbuf[6]
  1622. dp_irq2:
  1623.         jmp cs:dp_ointbuf[12]
  1624. dp_irq3:
  1625.         jmp cs:dp_ointbuf[18]
  1626. dp_irq4:
  1627.         jmp cs:dp_ointbuf[24]
  1628. dp_irq5:
  1629.         jmp cs:dp_ointbuf[30]
  1630. dp_irq6:
  1631.         jmp cs:dp_ointbuf[36]
  1632. dp_irq7:
  1633.         jmp cs:dp_ointbuf[42]
  1634. dp_irq8:
  1635.         jmp cs:dp_ointbuf[48]
  1636. dp_irq9:
  1637.         jmp cs:dp_ointbuf[54]
  1638. dp_irqa:
  1639.         jmp cs:dp_ointbuf[60]
  1640. dp_irqb:
  1641.         jmp cs:dp_ointbuf[66]
  1642. dp_irqc:
  1643.         jmp cs:dp_ointbuf[72]
  1644. dp_irqd:
  1645.         jmp cs:dp_ointbuf[78]
  1646. dp_irqe:
  1647.         jmp cs:dp_ointbuf[84]
  1648. dp_irqf:
  1649.         jmp cs:dp_ointbuf[90]
  1650.  
  1651. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1652. ; DPMI get IRQ handler offset
  1653. ; In:
  1654. ;   BL - IRQ num (0-0fh)
  1655. ; Out:
  1656. ;   EDX - offset of IRQ handler
  1657. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1658. dp_getirqvect:
  1659.         push ax ebx cx
  1660.         movzx ebx,bl
  1661.         mov bl,intslottbl[ebx]
  1662.         mov ax,204h
  1663.         int 31h
  1664.         pop cx ebx ax
  1665.         ret
  1666. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1667. ; DPMI set IRQ handler offset
  1668. ; In:
  1669. ;   BL - IRQ num (0-0fh)
  1670. ;   EDX - offset of IRQ handler
  1671. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1672. dp_setirqvect:
  1673.         push ax ebx cx
  1674.         movzx ebx,bl
  1675.         mov bl,intslottbl[ebx]
  1676.         mov cx,cs
  1677.         mov ax,205h
  1678.         int 31h
  1679.         pop cx ebx ax
  1680.         ret
  1681. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1682. ; Set the base addx for a selector
  1683. ; In:
  1684. ;   AX - selector
  1685. ;   EDX - linear base addx for selector
  1686. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1687. dp_setselector:
  1688. if SELECTORS ne 0
  1689.         push ax bx ecx
  1690.         shld ecx,edx,16
  1691.         mov bx,ax
  1692.         mov ax,7
  1693.         int 31h
  1694.         pop ecx bx ax
  1695. endif
  1696.         ret
  1697.  
  1698. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1699. ; 32 bit custom/XMS/VCPI system data
  1700. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1701. vp_vcpipmentry  df      3800000000h     ; VCPI entry point in pmode
  1702.  
  1703. cp_tssesp0ptr   dd      0               ; ptr to ESP0 in TSS, or null in VCPI
  1704. cp_idt32ptr     dd      ?               ; ptr to 32bit IDT
  1705. cp_validexcdesp dd      0               ; valid ESP value for exc 13
  1706.  
  1707. cp_v86irqintr   dd      offset cp_int33f0
  1708. cp_v86irqnum    db      ?               ; IRQ num for V86 mode
  1709. cp_savedstakoff dd      ?               ; current saved stack offset
  1710. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1711. ; 32 bit custom/XMS/VCPI system code
  1712. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1713. ;═════════════════════════════════════════════════════════════════════════════
  1714. cp_int31:                               ; INT 31h: AX=900h,901h,902h
  1715.         cmp al,1
  1716.         mov al,[esp+9]
  1717.         jb short cp_int31f0
  1718.         ja short cp_int31f1
  1719.         or byte ptr [esp+9],2
  1720.         jmp short cp_int31f1
  1721. cp_int31f0:
  1722.         and byte ptr [esp+9],0fdh
  1723. cp_int31f1:
  1724.         shr al,1
  1725.         and al,1
  1726.         iretd
  1727. ;═════════════════════════════════════════════════════════════════════════════
  1728. vp_int32:                               ; VCPI INT 32h: safe CX:DX=seg:off
  1729.         pushad
  1730.         mov ebp,offset callreal
  1731.         mov si,VICREAL1D
  1732.         mov bl,2
  1733.         jmp short cp_int34f0
  1734. ;═════════════════════════════════════════════════════════════════════════════
  1735. vp_int33:                               ; VCPI INT 33h: safe AL=int num
  1736.         pushad
  1737.         mov ebp,offset intreal
  1738. ;-----------------------------------------------------------------------------
  1739. vp_int33f0:
  1740.         mov si,VICREAL1D
  1741.         mov bl,2
  1742.         jmp short cp_int35f0
  1743. ;═════════════════════════════════════════════════════════════════════════════
  1744. cp_int32:                               ; INT 32h: safe CX:DX=seg:off
  1745.         pushad
  1746.         mov ebp,offset callreal
  1747.         mov si,CICREAL1D
  1748.         mov bl,1
  1749.         jmp short cp_int34f0
  1750. ;═════════════════════════════════════════════════════════════════════════════
  1751. cp_int33:                               ; INT 33h: safe AL=int num
  1752.         pushad
  1753.         mov ebp,offset intreal
  1754. ;-----------------------------------------------------------------------------
  1755. cp_int33f0:
  1756.         mov si,CICREAL1D
  1757.         mov bl,1
  1758.         jmp short cp_int35f0
  1759. ;-----------------------------------------------------------------------------
  1760. cp_int34f0:                             ; relic from times past
  1761.         shl ecx,16
  1762.         mov cx,dx
  1763.         mov bh,1
  1764.         jmp short cp_int3_
  1765. ;-----------------------------------------------------------------------------
  1766. cp_int35f0:                             ; another one, but functional
  1767.         movzx eax,al
  1768.         mov ecx,gs:[eax*4]
  1769.         xor bh,bh
  1770. ;-----------------------------------------------------------------------------
  1771. cp_int3_:                               ; int or call to real mode
  1772.         mov edi,[esp+40]
  1773.         shld eax,edi,23
  1774.         and al,bh
  1775.         add al,0fah
  1776.         mov edx,_code16a
  1777.         mov gs:icrealm0[edx],al
  1778.         mov gs:icrealm1[edx],ecx
  1779.         xchg gs:icrealm2[edx],si
  1780.         push si
  1781.         movzx esi,nextmodestack
  1782.         lea eax,[esi-STAKRMODE*16]
  1783.         mov nextmodestack,ax
  1784.         add eax,realstackbase
  1785.         mov edx,cp_tssesp0ptr
  1786.         push dword ptr [edx]
  1787.         mov [edx],eax
  1788.         sub eax,40
  1789.         push cp_validexcdesp
  1790.         mov cp_validexcdesp,eax
  1791.         push cp_savedstakoff
  1792.         mov cp_savedstakoff,esp
  1793.         cmp bl,1
  1794.         ja short vp_int3_s
  1795. ;-----------------------------------------------------------------------------
  1796. cp_int3_s:                              ; safe real mode int or call
  1797.         mov edx,_code16a
  1798.         mov gs:c_sicrealm0[edx],bp
  1799.         mov esp,esi
  1800.         db 0eah                 ; 16bit JMP FAR 20h:c_retreal0
  1801.         dw c_retreal0,0,20h     ;
  1802. ;-----------------------------------------------------------------------------
  1803. vp_int3_s:                              ; safe VCPI real mode int or call
  1804.         mov edi,ebp
  1805.         mov cx,v86r_ds
  1806.         mov ax,28h
  1807.         mov ds,ax
  1808.         db 0eah                 ; 16bit JMP FAR 20h:v_retreal0
  1809.         dw v_retreal0,0,20h     ;
  1810. ;-----------------------------------------------------------------------------
  1811. cp_int3_d:                              ; done with real mode int or call
  1812.         mov ax,18h
  1813.         mov gs,ax
  1814.         mov ax,10h
  1815.         mov ds,ax
  1816.         mov es,ax
  1817.         mov fs,ax
  1818.         mov ss,ax
  1819.         mov esp,cp_savedstakoff
  1820.         pop cp_savedstakoff
  1821.         pop cp_validexcdesp
  1822.         mov ebx,cp_tssesp0ptr
  1823.         pop dword ptr [ebx]
  1824.         mov ebx,_code16a
  1825.         pop gs:icrealm2[ebx]
  1826. ;-----------------------------------------------------------------------------
  1827. cp_int3_d3:                             ; done from real mode pmode call
  1828.         add nextmodestack,STAKRMODE*16
  1829.         mov bx,v86r_flags
  1830. ;-----------------------------------------------------------------------------
  1831. cp_int3_d2:                ; done from DPMI also
  1832.         mov ax,[esp+40]
  1833.         and ax,not 8d5h
  1834.         and bx,8d5h
  1835.         or ax,bx
  1836.         mov [esp+40],ax
  1837.         popad
  1838.         iretd
  1839. ;═════════════════════════════════════════════════════════════════════════════
  1840. ; low 8 exceptions and undefined interrupt.
  1841. cp_exc0:
  1842.         push eax
  1843.         xor al,al
  1844.         jmp cp_irq
  1845. cp_exc1:
  1846.         push eax
  1847.         mov al,1
  1848.         jmp cp_irq
  1849. cp_exc2:
  1850.         push eax
  1851.         mov al,2
  1852.         jmp cp_irq
  1853. cp_exc3:
  1854.         push eax
  1855.         mov al,3
  1856.         jmp cp_irq
  1857. cp_exc4:
  1858.         push eax
  1859.         mov al,4
  1860.         jmp cp_irq
  1861. cp_exc5:
  1862.         push eax
  1863.         mov al,5
  1864.         jmp cp_irq
  1865. cp_exc6:
  1866.         pushad
  1867.         mov al,6
  1868.         jmp short cp_exc
  1869. cp_exc7:
  1870.         push eax
  1871.         mov al,7
  1872.         jmp cp_irq
  1873. cp_excf:
  1874.         pushad
  1875.         mov al,0ffh
  1876. ;-----------------------------------------------------------------------------
  1877. cp_exc:                                 ; main exception handler
  1878.         mov bx,10h
  1879.         mov ds,bx
  1880.         mov es,bx
  1881.         mov fs,bx
  1882.         mov gs,_selzero
  1883.         cld
  1884.         jmp _exit
  1885. ;═════════════════════════════════════════════════════════════════════════════
  1886. ; IRQ redirector between modes
  1887. cp_irq0:
  1888.         push eax
  1889.         mov al,08h
  1890.         jmp short cp_irq
  1891. cp_irq1:
  1892.         push eax
  1893.         mov al,09h
  1894.         jmp short cp_irq
  1895. cp_irq2:
  1896.         push eax
  1897.         mov al,0ah
  1898.         jmp short cp_irq
  1899. cp_irq3:
  1900.         push eax
  1901.         mov al,0bh
  1902.         jmp short cp_irq
  1903. cp_irq4:
  1904.         push eax
  1905.         mov al,0ch
  1906.         jmp short cp_irq
  1907. cp_irq5:
  1908.         push eax
  1909.         mov al,0dh
  1910.         jmp short cp_irq
  1911. cp_irq6:
  1912.         push eax
  1913.         mov al,0eh
  1914.         jmp short cp_irq
  1915. cp_irq7:
  1916.         push eax
  1917.         mov al,0fh
  1918.         jmp short cp_irq
  1919. cp_irq8:
  1920.         push eax
  1921.         mov al,70h
  1922.         jmp short cp_irq
  1923. cp_irq9:
  1924.         push eax
  1925.         mov al,71h
  1926.         jmp short cp_irq
  1927. cp_irqa:
  1928.         push eax
  1929.         mov al,72h
  1930.         jmp short cp_irq
  1931. cp_irqb:
  1932.         push eax
  1933.         mov al,73h
  1934.         jmp short cp_irq
  1935. cp_irqc:
  1936.         push eax
  1937.         mov al,74h
  1938.         jmp short cp_irq
  1939. cp_irqd:
  1940.         push eax
  1941.         mov al,75h
  1942.         jmp short cp_irq
  1943. cp_irqe:
  1944.         push eax
  1945.         mov al,76h
  1946.         jmp short cp_irq
  1947. cp_irqf:
  1948.         push eax
  1949.         mov al,77h
  1950. ;─────────────────────────────────────────────────────────────────────────────
  1951. cp_irq:                                 ; main IRQ handler thingy
  1952.         mov ss:cp_v86irqnum,al
  1953.         pop eax
  1954.         push ds es fs gs
  1955.         pushfd
  1956.         push cs
  1957.         push offset cp_irqpd
  1958.         pushad
  1959.         mov ax,10h
  1960.         mov ds,ax
  1961.         mov al,18h
  1962.         mov gs,ax
  1963.         mov al,cp_v86irqnum
  1964.         mov ebp,offset c_irqreal
  1965.         jmp cp_v86irqintr
  1966. cp_irqpd:
  1967.         pop gs fs es ds
  1968.         iretd
  1969.  
  1970. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1971. ; Custom get IRQ handler offset
  1972. ; In:
  1973. ;   BL - IRQ num (0-0fh)
  1974. ; Out:
  1975. ;   EDX - offset of IRQ handler
  1976. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1977. cp_getirqvect:
  1978.         push ebx
  1979.         pushfd
  1980.         cli
  1981.         movzx ebx,bl
  1982.         mov bl,intslottbl[ebx]
  1983.         lea ebx,[ebx*8]
  1984.         add ebx,cp_idt32ptr
  1985.         mov dx,[ebx+6]
  1986.         shl edx,16
  1987.         mov dx,[ebx]
  1988.         popfd
  1989.         pop ebx
  1990.         ret
  1991. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1992. ; Custom set IRQ handler offset
  1993. ; In:
  1994. ;   BL - IRQ num (0-0fh)
  1995. ;   EDX - offset of IRQ handler
  1996. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1997. cp_setirqvect:
  1998.         push ebx edx
  1999.         pushfd
  2000.         cli
  2001.         movzx ebx,bl
  2002.         mov bl,intslottbl[ebx]
  2003.         lea ebx,[ebx*8]
  2004.         add ebx,cp_idt32ptr
  2005.         mov [ebx],dx
  2006.         shr edx,16
  2007.         mov [ebx+6],dx
  2008.         popfd
  2009.         pop edx ebx
  2010.         ret
  2011. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2012. ; Custom set the base addx for a selector
  2013. ; In:
  2014. ;   AX - selector
  2015. ;   EDX - linear base addx for selector
  2016. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2017. cp_setselector:
  2018. if SELECTORS ne 0
  2019.         push eax edx
  2020.         movzx eax,ax
  2021.         and edx,0ffffffh
  2022.         or edx,92000000h
  2023.         mov dword ptr gdt32[eax+2],edx
  2024.         mov dl,[esp+3]
  2025.         mov byte ptr gdt32[eax+7],dl
  2026.         pop edx eax
  2027. endif
  2028.         ret
  2029.  
  2030. code32  ends
  2031.  
  2032. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  2033. ; End of program (must be at end of program or you will suffer)
  2034. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  2035. codeend segment para stack use32 'stack'
  2036. db STAKSIZE*16 dup(?)
  2037. codeend ends
  2038.         end     start16
  2039.  
  2040.